package com.example.lt.service.impl;

import cn.hutool.core.io.IoUtil;
import com.example.lt.service.MinioService;
import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.minio.errors.*;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @Author 小涛Tao
 * @Date: 2024/06/03/13:58
 * version 1.0 注释：
 **/
@Service
@RequiredArgsConstructor
public class MinioServiceImpl implements MinioService {

    private final MinioClient minioClient;

    @Value("${minio.bucket}")
    private String bucketName;

    /**
     * 获取minio中的图片文件
     * @param filePath 文件路径
     * @param fileName 文件名称
     * @return
     * @throws Exception
     */
    public ResponseEntity<byte[]> getImage(String filePath, String fileName) throws Exception {
        InputStream stream = minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(filePath + fileName)
                        .build()
        );

        byte[] bytes = IoUtil.readBytes(stream);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_JPEG); // 设置响应内容类型为图片类型，根据实际情况修改

        return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
    }

    /**
     * 更新minio中的文件
     * @param filePath 文件的路径
     * @param fileName 文件的名称
     * @param file
     */
    public String uploadFile(String filePath, String fileName, MultipartFile file) {
        try {
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(filePath + fileName)
                            .stream(file.getInputStream(), file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build()
            );
        } catch (MinioException e) {
            System.err.println("Error occurred: " + e);
        } catch (IOException | NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
        }
        return "File uploaded successfully.";
    }

    /**
     * 删除minio中的文件
     * @param filePath 文件路径
     * @param fileName 文件名称
     */
    public String deleteFile(String filePath, String fileName) {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(filePath + fileName)
                            .build()
            );
        } catch (MinioException | InvalidKeyException | NoSuchAlgorithmException e) {
            System.err.println("Error occurred: " + e);
        } catch (IOException | IllegalArgumentException e) {
            e.printStackTrace();
        }
        return "File deleted successfully.";
    }

    /**
     * 获取minio中的音频
     * @param fileName
     * @return
     */
    public ResponseEntity<byte[]> getMusic(String filePath, String fileName) {
        try (InputStream inputStream = minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(filePath + fileName)
                        .build())) {

            byte[] bytes = IoUtil.readBytes(inputStream);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", fileName);

            return new ResponseEntity<>(bytes, headers, HttpStatus.OK);

        } catch (io.minio.errors.ErrorResponseException e) {
            // MinIO specific error response
            if (e.errorResponse().code().equals("NoSuchKey")) {
                return new ResponseEntity<>(HttpStatus.NOT_FOUND);
            } else {
                e.printStackTrace();
                return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 下载minio中的音频文件
     * @param filePath 音频文件的路径
     * @param fileName 音频文件的名称
     * @param request
     * @return
     */
    public ResponseEntity<Resource> downloadFile(String filePath, String fileName, HttpServletRequest request) {
        try {
            // 构建 MinIO 获取对象参数
            GetObjectArgs args = GetObjectArgs.builder()
                    .bucket(bucketName)
                    .object(filePath + fileName)
                    .build();
            // 获取文件输入流
            InputStream inputStream = minioClient.getObject(args);

            // 将文件内容读入 ByteArrayOutputStream
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            byte[] musicBytes = outputStream.toByteArray();

            // 创建 ByteArrayResource 对象
            ByteArrayResource resource = new ByteArrayResource(musicBytes);

            // 构建响应头
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + URLEncoder.encode(fileName, "UTF-8"));

            // 返回 ResponseEntity 对象
            return ResponseEntity.ok()
                    .headers(headers)
                    .contentLength(musicBytes.length)
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(resource);
        } catch (ServerException | InsufficientDataException | ErrorResponseException | IOException | NoSuchAlgorithmException | InvalidKeyException | InvalidResponseException | XmlParserException | InternalException e) {
            e.printStackTrace();
            // 返回内部服务器错误状态
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

}
